<template>
	<div class="hello">
		<div class="container">
			<div class="img-container">
				<img :src="imgurl" ref="imageRef" alt="" />
			</div>
			<div style="margin-left: 60px">
				<p>预览</p>
				<div class="before"></div>
				<p class="crosize" style="text-align: center; margin-top: 10px"></p>
				<!-- <div class="afterCropper">
					<img :src="afterImg" alt="" />
				</div> -->
			</div>
		</div>
		<div style="text-align: center">
			<el-button style="margin-top: 30px" type="primary" @click="sureSava">裁剪</el-button>
		</div>
	</div>
</template>

<script lang="ts" setup>
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
import { Base64 } from '/@/utils/b64';

const props = withDefaults(
	defineProps<{
		imgurl: string;
		config: Record<string, any>;
	}>(),
	{ imgurl: '', config: () => ({}) }
);
const emit = defineEmits(['cropperClone']);
const state = reactive({
	myCropper: null as Cropper | null,
	size: null as any,
	afterImg: '',
});
const imageRef = ref<InstanceType<typeof HTMLImageElement>>();
const init = () => {
	state.myCropper = new Cropper(imageRef.value!, {
		viewMode: 1,
		dragMode: 'none',
		preview: '.before',
		minCropBoxWidth: props.config && props.config.cropMode === 'free' ? 'none' : props.config.width,
		minCropBoxHeight: props.config && props.config.cropMode === 'free' ? 'none' : props.config.height,
		background: false,
		zoomOnWheel: false,
		cropBoxResizable: props.config && props.config.cropMode === 'free' ? true : false,
	});
	setTimeout(() => {
		if (props.config && props.config.cropMode === 'fixed') {
			state.myCropper?.setCropBoxData({ width: props.config.width, height: props.config.height });
		}
		document.getElementsByClassName('container')[0].onmousemove = () => {
			state.size = state.myCropper!.getCropBoxData();
			const croPele = document.getElementsByClassName('crosize')[0];
			croPele.innerHTML = state.size.width.toFixed(0) + ' × ' + state.size.height.toFixed(0);
		};
	}, 500);
};

const sureSava = () => {
	state.afterImg = state
		.myCropper!.getCroppedCanvas({
			imageSmoothingQuality: 'high',
		})
		.toDataURL('image/jpeg');
	const croImg = {
		raw: base64toFile(state.afterImg),
		size: base64ToBlob(state.afterImg).size,
		url: URL.createObjectURL(base64ToBlob(state.afterImg)),
	};
	console.log('sureSava', croImg);
	emit('cropperClone', croImg);
};
//base64转为普通文件格式
const base64toFile = (dataurl, filename = 'file') => {
	let arr = dataurl.split(',');
	let mime = arr[0].match(/:(.*?);/)[1];
	let suffix = mime.split('/')[1];
	let bstr = atob(arr[1]);
	let n = bstr.length;
	let u8arr = new Uint8Array(n);
	while (n--) {
		u8arr[n] = bstr.charCodeAt(n);
	}
	return new File([u8arr], `${filename}.${suffix}`, {
		type: mime,
	});
};

const base64ToBlob = (code) => {
	const parts = code.split(';base64,');
	const contentType = parts[0].split(':')[1];
	const raw = atob(parts[1]);
	const rawLength = raw.length;

	const uInt8Array = new Uint8Array(rawLength);

	for (let i = 0; i < rawLength; ++i) {
		uInt8Array[i] = raw.charCodeAt(i);
	}
	return new Blob([uInt8Array], {
		type: contentType,
	});
};
// const atob = (a: string) => {
// 	return Base64.decode(a);
// };
onMounted(() => {
	init();
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.container {
	display: flex;
}
.before {
	margin-top: 20px;
	width: 150px;
	height: 150px;
	overflow: hidden;
	/* 这个属性可以得到想要的效果 */
}
.img-container {
	height: 400px;
	overflow: hidden;
}
.afterCropper {
	flex: 1;
	margin-left: 20px;
	border: 1px solid salmon;
	text-align: center;
}
.afterCropper img {
	width: 150px;
	margin-top: 30px;
}
</style>
